Skip to content

Conversation

@vinay1359
Copy link

@vinay1359 vinay1359 commented Jan 14, 2026

Closes #238

📝 Description

This PR fixes several bugs that prevented the application from running properly.

What was broken:

Authentication wasn't working
Users could not log in to the website because the code was attempting to access user on a coroutine object instead of awaiting it first, resulting in authentication failures.

Repo stats endpoint was missing
The /api/repo-stats endpoint was defined in routes.py but was not registered with the main FastAPI application, causing the endpoint to return a 404 response.

Discord bot crashed on startup
The Discord bot attempted to run a cleanup task before the bot was fully initialized, which caused a runtime error during startup.

🔧 Changes Made

What I fixed:

File: dependencies.py
Added await before supabase.auth.get_user(token) so the async call completes before accessing the user object.

File: main.py
Imported the legacy router from routes.py and registered it with the FastAPI app using api.include_router(legacy_router, prefix="/api").
This makes the repo stats endpoint available at /api/repo-stats.

File: routes.py
Added the missing /repo-stats POST endpoint implementation.
The endpoint uses httpx to call the GitHub API, fetches repository data (stars, forks, issues, etc.), parses the repository URL, and returns structured JSON.

File: cogs.py
Improved the cleanup task to wait until the Discord bot is fully ready before running.
Added logging to indicate when the task is waiting versus running.
Fixed the cog_unload method to check whether the task is running before attempting to cancel it.

Testing:

  • Verified the authentication flow by logging in through the website successfully.
  • Confirmed that the /api/repo-stats endpoint returns valid GitHub repository data.
  • Started the Discord bot and verified that it initializes without errors and that the cleanup task waits until the bot is fully ready.

✅ Checklist

  • [✅] I have read the contributing guidelines.
  • [✅ ] I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if applicable).
  • Any dependent changes have been merged and published in downstream modules.

Summary by CodeRabbit

  • New Features

    • Added API endpoint to fetch GitHub repository statistics (name, stars, forks, open issues, language, timestamps).
    • Registered legacy API router under /api.
  • Bug Fixes

    • Fixed asynchronous authentication so token verification runs correctly.
    • Improved Discord integration lifecycle to avoid unnecessary task cancellations and added startup trace logs.
  • Chores

    • Updated Discord integration library version.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

Warning

Rate limit exceeded

@vinay1359 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 6 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between dd2e6c0 and 5c6affc.

📒 Files selected for processing (1)
  • backend/routes.py
📝 Walkthrough

Walkthrough

Fixes Supabase auth coroutine by awaiting token verification, adds a POST /repo-stats endpoint that fetches GitHub repo metadata, registers the legacy router under /api, adjusts Discord cog lifecycle to avoid cancelling idle cleanup tasks, and bumps the discord.py dependency range.

Changes

Cohort / File(s) Summary
Authentication
backend/app/core/dependencies.py
get_current_user now awaits supabase.auth.get_user(token) (fixed coroutine usage); existing HTTP error handling preserved
Repo stats API
backend/routes.py
Added POST /repo-stats (get_repo_stats) that parses repo URLs (SSH/HTTPS), validates input and presence of GitHub token, calls GitHub REST API via httpx with Authorization, handles non-200 responses, and returns structured repo metadata
Route registration
backend/main.py
Imports and registers legacy_router from routes under prefix /api with tag Legacy
Discord bot lifecycle
backend/integrations/discord/cogs.py
cog_load starts periodic cleanup task; cog_unload cancels the cleanup task only if running; before_loop adds debug prints around bot readiness wait
Dependencies
pyproject.toml
Bumped discord.py dependency range from >=2.4.0,<2.5.0 to >=2.6.4,<3.0.0

Sequence Diagram(s)

sequenceDiagram
    participant Client as Frontend Client
    participant API as Backend /repo-stats
    participant GitHub as GitHub REST API

    Client->>API: POST /api/repo-stats { repo_url }
    activate API
    API->>API: Parse owner/repo\nValidate URL and GitHub token
    alt valid
        API->>GitHub: GET /repos/{owner}/{repo} (Authorization)
        activate GitHub
        GitHub-->>API: 200 OK + repo metadata
        deactivate GitHub
        API->>API: Extract fields (name, stars, forks, owner, etc.)
        API-->>Client: 200 OK + structured repo data
    else invalid or error
        API-->>Client: 400/401/500 Error
    end
    deactivate API
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • smokeyScraper

Poem

🐰 I hopped into code with a cheer,

Awaited tokens now appear,
Repo stats fetched from GitHub's shore,
Discord idles cleaned no more,
The rabbit hops and fixes more! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive The discord-py dependency bump (>=2.6.4,<3.0.0) in pyproject.toml appears unrelated to the three core fixes and may represent scope creep unless required for the Discord bot fixes. Clarify whether the discord-py dependency bump was necessary for the bot startup fixes or if it should be deferred to a separate update PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: fixing authentication, repo-stats API, and Discord bot startup issues, matching the primary objectives in the PR.
Linked Issues check ✅ Passed All three objectives from issue #238 are addressed: authentication fixed with await in dependencies.py, /api/repo-stats endpoint implemented in routes.py and registered in main.py, and Discord bot startup fixed in cogs.py with task lifecycle improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@backend/routes.py`:
- Around line 54-58: Before building the GitHub API request headers in
backend/routes.py, validate that settings.github_token is set (non-empty) and
handle the missing token like in backend/app/services/github/user/profiling.py:
check settings.github_token, and if absent raise or return a clear error (or log
and abort the request) with an explanatory message about the missing GitHub
token so you don’t construct an invalid Authorization header; update the code
path that constructs headers = {"Authorization": f"token
{settings.github_token}", ...} to only run after this validation.
- Around line 46-52: The repo_url parsing is brittle; update the logic around
request.repo_url (and the variables repo_url, parts, owner, repo) to normalize
and robustly handle SSH URLs, URLs without protocol, and .git suffixes: first
trim whitespace, handle SSH format starting with "git@" by splitting on ":" to
get the path, otherwise ensure a scheme (prepend "https://" if missing) and use
a URL parser to get the path, strip leading/trailing slashes and any trailing
".git", split the path into segments, validate there are at least two segments,
then assign owner = segments[0] and repo = segments[1]; raise the same
HTTPException on invalid inputs.
🧹 Nitpick comments (2)
backend/integrations/discord/cogs.py (1)

43-45: Consider using logger.debug() instead of print() for consistency.

The file uses logger elsewhere (e.g., line 47). Using print() for tracing bypasses log configuration (levels, formatting, handlers) and may clutter stdout in production.

♻️ Suggested refactor
     async def cleanup_expired_tokens(self):
         """Periodic cleanup of expired verification tokens"""
         try:
-            print("--> Running token cleanup task...")
+            logger.debug("Running token cleanup task...")
             await cleanup_expired_tokens()
-            print("--> Token cleanup task finished.")
+            logger.debug("Token cleanup task finished.")
         except Exception as e:
             logger.error(f"Error during token cleanup: {e}")

     `@cleanup_expired_tokens.before_loop`
     async def before_cleanup(self):
         """Wait until the bot is ready before starting cleanup"""
-        print("--> Waiting for bot to be ready before starting cleanup task...")
+        logger.debug("Waiting for bot to be ready before starting cleanup task...")
         await self.bot.wait_until_ready()
-        print("--> Bot is ready, starting cleanup task...")
+        logger.debug("Bot is ready, starting cleanup task...")

Also applies to: 52-54

backend/routes.py (1)

91-95: Improve exception handling per best practices.

The static analysis hints are valid here. Consider:

  1. Using logging.exception to capture stack traces
  2. Using raise ... from e for exception chaining
  3. Avoiding exposing internal error details to clients
♻️ Suggested improvement
     except HTTPException:
         raise
     except Exception as e:
-        logging.error(f"Error fetching repo stats: {e}")
-        raise HTTPException(status_code=500, detail=str(e))
+        logging.exception("Error fetching repo stats")
+        raise HTTPException(status_code=500, detail="Failed to fetch repository statistics") from e
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa66519 and 0d0ac2a.

⛔ Files ignored due to path filters (2)
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • backend/app/core/dependencies.py
  • backend/integrations/discord/cogs.py
  • backend/main.py
  • backend/routes.py
  • pyproject.toml
🧰 Additional context used
🧬 Code graph analysis (1)
backend/integrations/discord/cogs.py (1)
backend/app/core/orchestration/queue_manager.py (1)
  • start (47-56)
🪛 Ruff (0.14.11)
backend/routes.py

50-50: Abstract raise to an inner function

(TRY301)


68-71: Abstract raise to an inner function

(TRY301)


93-93: Do not catch blind exception: Exception

(BLE001)


94-94: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


95-95: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🔇 Additional comments (4)
backend/integrations/discord/cogs.py (1)

35-37: LGTM! Good defensive check before cancellation.

Checking is_running() before calling cancel() prevents potential errors when the task hasn't started or has already completed.

pyproject.toml (1)

11-11: Remove unused py-cord dependency.

Both py-cord and discord-py are listed in pyproject.toml (lines 11 and 29), but the codebase only imports from discord (discord.py). The py-cord dependency is unused and should be removed to avoid unnecessary bloat and potential namespace conflicts.

backend/app/core/dependencies.py (1)

47-59: LGTM! Correct fix for the async authentication bug.

The await keyword properly resolves the coroutine before accessing user_response.user, fixing the "coroutine object has no attribute 'user'" error. The get_supabase_client() function returns an AsyncClient instance, and supabase.auth.get_user(token) is correctly awaited. Error handling is well-structured.

backend/main.py (1)

17-17: Router registration is correct with no route conflicts.

The legacy router is properly imported and registered with the /api prefix. Routes are cleanly separated: legacy endpoints at /api/repo-stats and /api/github/webhook, while the main API routes remain under /v1/*.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@backend/routes.py`:
- Around line 124-128: The generic exception handler leaks internal details and
doesn't preserve traceback; replace the current block so that you call
logging.exception(...) to log the error with its traceback, return a generic
client-facing message (e.g., "Internal server error") instead of str(e) when
raising HTTPException, and re-raise using exception chaining (raise
HTTPException(status_code=500, detail="Internal server error") from e) so the
original exception context is preserved; update the except Exception as e: block
in backend/routes.py accordingly.
🧹 Nitpick comments (2)
backend/routes.py (2)

62-69: Unreachable exception handler.

The except (IndexError, ValueError) block at lines 68-69 is dead code. Since line 64 already checks if "github.com/" in repo_url, the split("github.com/", 1)[1] on line 65 will always succeed and return a string (never raise IndexError or ValueError).

♻️ Suggested simplification
             # Extract path from URL
-            try:
-                # Parse URL to get path component
-                if "github.com/" in repo_url:
-                    path = repo_url.split("github.com/", 1)[1]
-                else:
-                    raise HTTPException(status_code=400, detail="Invalid GitHub repository URL")
-            except (IndexError, ValueError):
+            # Parse URL to get path component
+            if "github.com/" in repo_url:
+                path = repo_url.split("github.com/", 1)[1]
+            else:
                 raise HTTPException(status_code=400, detail="Invalid GitHub repository URL")

79-97: Fix inconsistent indentation on comment lines.

Lines 80 and 86 have extra leading whitespace before the comments, causing misalignment with the surrounding code. This appears to be a formatting error.

♻️ Suggested fix
         owner, repo = segments[0], segments[1]
-                # Validate GitHub token is configured
+        
+        # Validate GitHub token is configured
         if not settings.github_token:
             raise HTTPException(
                 status_code=500,
                 detail="GitHub token not configured in environment variables. Please set GITHUB_TOKEN."
             )
-                # Fetch repository stats from GitHub API
+        
+        # Fetch repository stats from GitHub API
         headers = {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d0ac2a and 7cdc625.

📒 Files selected for processing (1)
  • backend/routes.py
🧰 Additional context used
🪛 Ruff (0.14.11)
backend/routes.py

55-55: Abstract raise to an inner function

(TRY301)


69-69: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


77-77: Abstract raise to an inner function

(TRY301)


82-85: Abstract raise to an inner function

(TRY301)


101-104: Abstract raise to an inner function

(TRY301)


126-126: Do not catch blind exception: Exception

(BLE001)


127-127: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


128-128: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🔇 Additional comments (3)
backend/routes.py (3)

10-11: LGTM!

The imports for settings and httpx are appropriate for the new repo-stats endpoint functionality.


15-16: LGTM!

The RepoRequest model is simple and sufficient. URL validation is handled in the endpoint logic.


99-123: LGTM!

The error handling now logs the full error details server-side while returning a sanitized message to clients, addressing the previous concern about exposing raw GitHub API responses. The response structure is well-organized.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@backend/routes.py`:
- Around line 68-69: The except block catching IndexError/ValueError should
preserve the original exception context: change it to "except (IndexError,
ValueError) as e:" and re-raise the HTTPException using exception chaining
(e.g., "raise HTTPException(status_code=400, detail='Invalid GitHub repository
URL') from e") so the original error is retained for debugging while still
returning the HTTPException to callers.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7cdc625 and dd2e6c0.

📒 Files selected for processing (1)
  • backend/routes.py
🧰 Additional context used
🪛 Ruff (0.14.11)
backend/routes.py

55-55: Abstract raise to an inner function

(TRY301)


69-69: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


77-77: Abstract raise to an inner function

(TRY301)


82-85: Abstract raise to an inner function

(TRY301)


101-104: Abstract raise to an inner function

(TRY301)

🔇 Additional comments (4)
backend/routes.py (4)

10-11: LGTM!

Appropriate imports for the new functionality - settings for configuration access and httpx for async HTTP requests.


15-16: LGTM!

Simple and functional request model. URL validation is handled in the endpoint logic.


80-104: LGTM - Token validation and API error handling are well implemented.

Good practices applied:

  • Token validation before making the API request
  • Error details logged server-side while returning a sanitized message to the client
  • Reasonable timeout configured for the external call

Minor cosmetic note: Lines 80 and 86 have inconsistent comment indentation.


106-128: LGTM - Response structure and exception handling are well implemented.

The response returns a clean, structured subset of repository data. The exception handling correctly:

  • Re-raises HTTPException without modification
  • Uses logging.exception for automatic traceback inclusion
  • Returns a generic error message to clients
  • Preserves exception context with from e

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: Authentication failure, missing repo-stats API endpoint, and Discord bot startup errors

1 participant